﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.IO;
using System.Web;

namespace Web.Ajax.Data
{
	public class Storage : Attribute
	{
		public long InitialId = 1000;
		public int Increment = 1;
		public Type Type;
		public bool AllowCaching = true;

		//public string Path;  //  Company\\[CompanyId]\\

		public string GetBaseFolder()
		{
			return Configuration.Settings.Current.DataFolder;
		}
		public virtual string GetFolder()
		{
			string Folder = GetBaseFolder();
			Folder += Type.Name + "\\";
			if (!Directory.Exists(Folder))
				Directory.CreateDirectory(Folder);
			return Folder;
		}

		public bool FileExists(long Id)
		{
			var f = GetFileName(Id);
			if (File.Exists(f))
				return true;
			return false;
		}

		public string GetFileName(long Id)
		{
			return GetFolder() + Id.ToString() + ".json";
		}

		public static Storage GetStorage(System.Type t)
		{
			var s = new Storage();
			var list = (Storage[])t.GetCustomAttributes(typeof(Storage), true);
			if (list != null && list.Length == 1)
				s = list[0];
			s.Type = t;
			return s;
		}

		public Object Get(System.Type t, long Id)
		{
			string FileName = GetFileName(Id);
			if (File.Exists(FileName))
				return (Object)Json.Load(FileName, t);
			return null;
		}


		[ThreadStatic]
		private static Hashtable cache = new Hashtable();
		public class CacheEntry
		{
			public DateTime Timeout;
			public object Object;
		}

		public static object GetCache(string key)
		{
			CacheEntry ce = null;
			if (HttpContext.Current != null)
			{
				ce = (CacheEntry)HttpContext.Current.Items[key];
			}
			else
			{
				if (cache == null)
					cache = new Hashtable();
				if (cache.ContainsKey(key))
					ce = (CacheEntry)cache[key];
			}
			if (ce != null && ce.Timeout > DateTime.Now)
				return ce.Object;
			return null;
		}
		public static void SetCache(string key, CacheEntry c)
		{
			if (HttpContext.Current != null)
				HttpContext.Current.Items[key] = c;
			else
			{
				if (cache == null)
					cache = new Hashtable();
				cache[key] = c;
			}
		}
		public static void ClearCache(string key)
		{
			SetCache(key, null);
		}


		public Array Get()
		{
			ArrayList list = new ArrayList();
			string Folder = GetFolder();


			if (AllowCaching)
			{
				var obj = GetCache(Folder);
				if (obj != null)
					return (Array)obj;
			}

			if (Directory.Exists(Folder))
			{
				string[] files = Directory.GetFiles(Folder, "*.json");
				for (int i = 0; i < files.Length; i++)
				{
					string FileName = files[i];
					list.Add(Json.Load(FileName, Type));
				}
			}
			var arr = list.ToArray(Type);


			if (AllowCaching)
				SetCache(Folder, new CacheEntry { Timeout = DateTime.Now.AddSeconds(10.0), Object = arr });


			return arr;
		}

		public void Save(Object o)
		{
			if (o.Id == -1)
				o.Id = GetNextId(o, this);
			string FileName = GetFileName(o.Id);
			Json.Save(FileName, o);
			ClearCache(GetFolder());
		}

		public void Delete(long? Id, long? ParentId)
		{
			if (!Id.HasValue || Id.Value == -1)
				return;
			string FileName = GetFileName(Id.Value);
			if (File.Exists(FileName))
				File.Delete(FileName);
		}

		public static long GetNextId(Object o, Storage s)
		{
			var f = s.GetFolder();
			var fnl=Directory.GetFiles(f, "*.json");
			var nid = s.InitialId;
			if (fnl != null)
			{
				foreach (var fn in fnl)
				{
					var ids = fn.Substring(fn.LastIndexOf("\\")+1).ToLower().Replace(".json", "");

					if (!System.Text.RegularExpressions.Regex.IsMatch(ids,"^\\d+$"))
						continue;
					var eid=long.Parse(ids);
					if(eid>=nid)
						nid = eid + s.Increment;
				}
			}
			return nid;
		}
	}
}
